﻿/*----------------------------------------------------------------
//  <copyright file="RoleStoreBase.cs" company="MicroCloud@151504200868">
//      Copyright © 2020-2024 MicroCloud Corporation, All rights reserved.
//  </copyright>
//  <site>https://gitee.com/chenmm123/microclouds</site>
//  <last-editor>cmm</last-editor>
//  <last-date>2023-09-21 09:59</last-date>
//----------------------------------------------------------------*/

namespace MicroCloud.Identity
{
    #region "角色存储基类"
    /// <summary>
    /// 角色存储基类
    /// </summary>
    /// <typeparam name="TRole">角色实体类型</typeparam>
    /// <typeparam name="TRoleKey">角色编号类型</typeparam>
    /// <typeparam name="TRoleClaim">角色声明实体类型</typeparam>
    /// <typeparam name="TRoleClaimKey">角色声明编号类型</typeparam>
    /// <typeparam name="TUserRole">用户角色实体类型</typeparam>
    /// <typeparam name="TUserRoleKey">用户角色编号类型</typeparam>
    /// <typeparam name="TUser">用户实体类型</typeparam>
    /// <typeparam name="TUserKey">用户编号类型</typeparam>
    /// <typeparam name="TOrganization">组织机构实体类型</typeparam>
    /// <typeparam name="TOrganizationKey">组织机构编号类型</typeparam>
    /// <typeparam name="TRoleOrganization">角色组织机构实体类型</typeparam>
    /// <typeparam name="TRoleOrganizationKey">角色组织机构编号类型</typeparam>
    public abstract class RoleStoreBase<TRole, TRoleKey, TRoleClaim, TRoleClaimKey, TUserRole, TUserRoleKey, TUser, TUserKey, TOrganization, TOrganizationKey, TRoleOrganization, TRoleOrganizationKey>
        : Disposable, IQueryableRoleStore<TRole>,
          IRoleClaimStore<TRole>,
          IRoleUserStore<TRole>,
          IRoleOrganizationStore<TRole>
        where TRole : RoleBase<TRoleKey, TUserKey>
        where TRoleClaim : RoleClaimBase<TRoleClaimKey, TRoleKey>, new()
        where TRoleKey : struct, IEquatable<TRoleKey>
        where TRoleClaimKey : struct, IEquatable<TRoleClaimKey>
        where TUserRole : UserRoleBase<TUserRoleKey, TUserKey, TRoleKey>, new()
        where TUserRoleKey : struct, IEquatable<TUserRoleKey>
        where TUser : UserBase<TUserKey>
        where TUserKey : struct, IEquatable<TUserKey>
        where TOrganization : OrganizationBase<TOrganizationKey, TUserKey>
        where TOrganizationKey : struct, IEquatable<TOrganizationKey>
        where TRoleOrganization : RoleOrganizationBase<TRoleOrganizationKey, TRoleKey, TOrganizationKey>, new()
        where TRoleOrganizationKey : struct, IEquatable<TRoleOrganizationKey>
    {
        //字段
        private readonly IRepository<TRole, TRoleKey> _roleRepository;
        private readonly IRepository<TRoleClaim, TRoleClaimKey> _roleClaimRepository;
        private readonly IRepository<TUserRole, TUserRoleKey> _userRoleRepository;
        private readonly UserManager<TUser> _userManager;
        private readonly IRepository<TOrganization, TOrganizationKey> _organizationRepository;
        private readonly IRepository<TRoleOrganization, TRoleOrganizationKey> _roleOrganizationRepository;
        private readonly IEventBus _eventBus;

        #region "属性"
        #region "获取 角色集合 - IQueryableRoleStore<TRole>的实现"
        /// <summary>
        /// 获取 角色集合
        /// </summary>
        public IQueryable<TRole> Roles => _roleRepository.QueryAsNoTracking();
        #endregion

        #endregion

        #region "构造函数"
        #region "初始化一个角色存储基类的新实例"
        /// <summary>
        /// 初始化一个角色存储基类 <see cref="RoleStoreBase{TRole, TRoleKey, TRoleClaim, TRoleClaimKey, TUserRole, TUserRoleKey, TUser, TUserKey, TOrganization, TOrganizationKey, TRoleOrganization, TRoleOrganizationKey}"/> 的新实例
        /// </summary>
        /// <param name="roleRepository">角色仓储</param>
        /// <param name="roleClaimRepository">角色声明仓储</param>
        /// <param name="userRoleRepository">用户角色仓储</param>
        /// <param name="userManager">用户管理器</param>
        /// <param name="organizationRepository">组织机构仓储</param>
        /// <param name="roleOrganizationRepository">角色组织机构仓储</param>
        /// <param name="eventBus">事件总线</param>
        protected RoleStoreBase(
            IRepository<TRole, TRoleKey> roleRepository,
            IRepository<TRoleClaim, TRoleClaimKey> roleClaimRepository,
            IRepository<TUserRole, TUserRoleKey> userRoleRepository,
            UserManager<TUser> userManager,
            IRepository<TOrganization, TOrganizationKey> organizationRepository,
            IRepository<TRoleOrganization, TRoleOrganizationKey> roleOrganizationRepository,
            IEventBus eventBus
            )
        {
            _roleRepository = roleRepository;
            _roleClaimRepository = roleClaimRepository;
            _userRoleRepository = userRoleRepository;
            _userManager = userManager;
            _organizationRepository = organizationRepository;
            _roleOrganizationRepository = roleOrganizationRepository;
            _eventBus = eventBus;
        }
        #endregion

        #endregion

        #region "其他方法"
        #region "将提供的<paramref name="id"/>转换为强类型键对象"
        /// <summary>
        /// 将提供的<paramref name="id"/>转换为强类型键对象
        /// </summary>
        /// <param name="id">要转换的id</param>
        /// <returns><typeparamref name="TRoleKey"/>的实例表示提供的<paramref name="id"/></returns>
        public virtual TRoleKey ConvertIdFromString(string id)
        {
            if (id == null)
            {
                return default;
            }

            return (TRoleKey)TypeDescriptor.GetConverter(typeof(TRoleKey)).ConvertFromInvariantString(id);
        }
        #endregion
        #region "将提供的<paramref name="id"/>转换为其字符串表示形式"
        /// <summary>
        /// 将提供的<paramref name="id"/>转换为其字符串表示形式
        /// </summary>
        /// <param name="id">要转换的id</param>
        /// <returns>提供<paramref name="id"/>的<see cref="string"/>的表示</returns>
        public virtual string ConvertIdToString(TRoleKey id)
        {
            if (id.Equals(default))
            {
                return null;
            }

            return id.ToString();
        }
        #endregion

        #region "如果已释放，则抛出异常"
        /// <summary>
        /// 如果已释放，则抛出异常
        /// </summary>
        protected virtual void ThrowIfDisposed()
        {
            if (Disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }
        }
        #endregion

        #endregion

        #region "方法 - Implementation of IRoleStore<TRole>"
        #region "异步在存储中创建一个新角色"
        /// <summary>
        /// 异步在存储中创建一个新角色
        /// </summary>
        /// <param name="role">要在存储中创建的角色</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="IdentityResult" /></returns>
        public virtual async Task<IdentityResult> CreateAsync(TRole role, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            if (role.IsDefault)
            {
                string defaultRole = _roleRepository.QueryAsNoTracking(m => m.IsDefault, false).Select(m => m.Name).FirstOrDefault();
                if (defaultRole != null)
                {
                    return new IdentityResult().Failed(I18N.T("系统中已存在默认角色 {0}", defaultRole));
                }
            }

            var operationResult = await _roleRepository.InsertAsync(role);
            if (operationResult.Succeeded)
            {
                //触发创建事件
                EntityEventData<TRole> eventData = new(_roleRepository.DbContext, OperateType.Insert) { Entities = new List<TRole> { role } };
                await _eventBus?.PublishAsync(eventData);

                return IdentityResult.Success;
            }
            return new IdentityResult().Failed(operationResult.Message);
        }
        #endregion
        #region "异步更新存储中的角色"
        /// <summary>
        /// 异步更新存储中的角色
        /// </summary>
        /// <param name="role">要在存储中更新的角色</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="IdentityResult" /></returns>
        public virtual async Task<IdentityResult> UpdateAsync(TRole role, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            if (role.IsSystem)
            {
                return new IdentityResult().Failed(I18N.T("不能更新系统角色 {0}", role.Name));
            }

            if (role.IsDefault)
            {
                var defaultRole = _roleRepository.QueryAsNoTracking(m => m.IsDefault, false).Select(m => new { m.Id, m.Name }).FirstOrDefault();
                if (defaultRole != null && !defaultRole.Id.Equals(role.Id))
                {
                    return new IdentityResult().Failed(I18N.T("系统中已存在默认角色 {0}", defaultRole));
                }
            }

            var operationResult = await _roleRepository.UpdateAsync(role);
            switch (operationResult.ResultType)
            {
                case OperationResultType.Success:
                    //触发更新事件
                    EntityEventData<TRole> eventData = new(_roleRepository.DbContext, OperateType.Update) { Entities = new List<TRole> { role } };
                    await _eventBus?.PublishAsync(eventData);

                    return IdentityResult.Success;
            }

            return new IdentityResult().Failed(operationResult.Message);
        }
        #endregion
        #region "异步删除存储中的角色"
        /// <summary>
        /// 异步删除存储中的角色
        /// </summary>
        /// <param name="role">要从存储中删除的角色</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="IdentityResult" /></returns>
        public virtual async Task<IdentityResult> DeleteAsync(TRole role, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            if (role.IsSystem)
            {
                return new IdentityResult().Failed(I18N.T("不能删除系统角色 {0}", role.Name));
            }

            var operationResult = await _roleRepository.DeleteAsync(role);
            if (operationResult.Succeeded)
            {
                //触发删除事件
                EntityEventData<TRole> eventData = new(_roleRepository.DbContext, OperateType.Delete) { Entities = new List<TRole> { role } };
                await _eventBus?.PublishAsync(eventData);

                return IdentityResult.Success;
            }
            return new IdentityResult().Failed(operationResult.Message);
        }
        #endregion
        #region "异步从存储区获取角色的ID"
        /// <summary>
        /// 异步从存储区获取角色的ID
        /// </summary>
        /// <param name="role">应返回其ID的角色</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns>包含角色ID的<see cref="Task" />结果</returns>
        public virtual async Task<string> GetRoleIdAsync(TRole role, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            return await Task.FromResult(ConvertIdToString(role.Id));
        }
        #endregion
        #region "异步从存储区获取角色的名称"
        /// <summary>
        /// 异步从存储区获取角色的名称
        /// </summary>
        /// <param name="role">应返回其名称的角色</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns>包含角色名称的<see cref="Task" />结果</returns>
        public virtual async Task<string> GetRoleNameAsync(TRole role, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            return await Task.FromResult(role.Name);
        }
        #endregion
        #region "异步设置存储区中角色的名称"
        /// <summary>
        /// 异步设置存储区中角色的名称
        /// </summary>
        /// <param name="role">应设置其名称的角色</param>
        /// <param name="roleName">要设置角色的名称</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />结果</returns>
        public virtual async Task SetRoleNameAsync(TRole role, string roleName, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            role.Name = roleName;
            await Task.CompletedTask;
        }
        #endregion
        #region "异步获取角色的规范化名称"
        /// <summary>
        /// 异步获取角色的规范化名称
        /// </summary>
        /// <param name="role">应检索其规范化名称的角色</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns>包含角色规范化名称的<see cref="Task" />结果</returns>
        public virtual async Task<string> GetNormalizedRoleNameAsync(TRole role, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            return await Task.FromResult(role.NormalizedName);
        }
        #endregion
        #region "异步设置角色的规范化名称"
        /// <summary>
        /// 异步设置角色的规范化名称
        /// </summary>
        /// <param name="role">应设置其规范化名称的角色</param>
        /// <param name="normalizedName">要设置的规范化名称</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />结果</returns>
        public virtual async Task SetNormalizedRoleNameAsync(TRole role, string normalizedName, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            role.NormalizedName = normalizedName;
            await Task.CompletedTask;
        }
        #endregion
        #region "异步查找具有指定ID的角色"
        /// <summary>
        /// 异步查找具有指定ID的角色
        /// </summary>
        /// <param name="roleId">要查找的角色ID</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns>包含角色的<see cref="Task" />结果</returns>
        public virtual async Task<TRole> FindByIdAsync(string roleId, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();

            TRoleKey id = ConvertIdFromString(roleId);
            return await Task.FromResult(_roleRepository.Get(id));
        }
        #endregion
        #region "异步查找具有指定规范化名称的角色"
        /// <summary>
        /// 异步查找具有指定规范化名称的角色
        /// </summary>
        /// <param name="normalizedRoleName">要查找的规范化角色名称</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns>包含角色的<see cref="Task" />结果</returns>
        public virtual async Task<TRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            return await Task.FromResult(Roles.FirstOrDefault(m => m.NormalizedName == normalizedRoleName));
        }
        #endregion

        #endregion

        #region "方法 - Implementation of IRoleUserStore<TRole>"
        #region "将指定的角色添加到用户"
        /// <summary>
        /// 将指定的角色添加到用户
        /// </summary>
        /// <param name="role">角色实体</param>
        /// <param name="userId">用户编号</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="OperationResult" /></returns>
        public virtual async Task<OperationResult> AddToUserAsync(TRole role, string userId, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNullOrEmpty(userId, nameof(userId));

            TUserKey userKey = _userManager.Users.Where(m => m.Id.Equals(userId.CastTo<TUserKey>())).Select(m => m.Id).FirstOrDefault();
            if (Equals(userKey, default(TUserKey)))
            {
                throw new InvalidOperationException(I18N.T("用户 {0} 不存在", userId));
            }
            TUserRole userRole = new() { RoleId = role.Id, UserId = userKey };
            return await _userRoleRepository.InsertAsync(userRole);
        }
        #endregion
        #region "将指定的角色添加到用户集合"
        /// <summary>
        /// 将指定的角色添加到用户集合
        /// </summary>
        /// <param name="role">角色实体</param>
        /// <param name="userIds">用户名称集合</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="OperationResult" /></returns>
        public virtual async Task<OperationResult> AddToUsersAsync(TRole role, string[] userIds, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNull(userIds, nameof(userIds));

            foreach (var userId in userIds)
            {
                var result = await AddToUserAsync(role, userId, cancellationToken);
                if (!result.Succeeded)
                {
                    return result;
                }
            }
            return OperationResult.Success();
        }
        #endregion
        #region "从用户中删除指定的角色"
        /// <summary>
        /// 从用户中删除指定的角色
        /// </summary>
        /// <param name="role">角色实体</param>
        /// <param name="userId">用户编号</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="OperationResult" /></returns>
        public virtual async Task<OperationResult> RemoveFromUserAsync(TRole role, string userId, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNullOrEmpty(userId, nameof(userId));

            var user = _userManager.Users.Where(m => m.Id.Equals(userId.CastTo<TUserKey>())).Select(o => new { o.Id, o.UserName, o.NickName, o.IsSystem }).FirstOrDefault() ?? throw new InvalidOperationException(I18N.T("用户 {0} 不存在", userId));
            if (role.IsSystem && user.IsSystem)
            {
                throw new InvalidOperationException(I18N.T("系统角色 {0} 的系统用户 {1} 不能移除", role.Name, user.UserName));
            }
            return await _userRoleRepository.DeleteBatchAsync(m => m.UserId.Equals(user.Id) && m.RoleId.Equals(role.Id));
        }
        #endregion
        #region "从用户集合中删除指定的角色"
        /// <summary>
        /// 从用户集合中删除指定的角色
        /// </summary>
        /// <param name="role">角色实体</param>
        /// <param name="userIds">用户编号集合</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="OperationResult" /></returns>
        public virtual async Task<OperationResult> RemoveFromUsersAsync(TRole role, string[] userIds, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNull(userIds, nameof(userIds));

            foreach (var userId in userIds)
            {
                var result = await RemoveFromUserAsync(role, userId, cancellationToken);
                if (!result.Succeeded)
                {
                    return result;
                }
            }
            return OperationResult.Success();
        }
        #endregion
        #region "获取设置当前角色的用户编号集合"
        /// <summary>
        /// 获取设置当前角色的用户编号集合
        /// </summary>
        /// <param name="role">角色实体</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns>包含用户编号集合的<see cref="Task" />结果</returns>
        public virtual async Task<IList<string>> GetUsersAsync(TRole role, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            List<string> userIds = _userRoleRepository.QueryAsNoTracking(m => m.RoleId.Equals(role.Id)).Select(m => m.UserId.ToString()).ToList();
            return await Task.FromResult(userIds);
        }
        #endregion
        #region "返回一个标志，指示指定的角色是否为给定用户的成员"
        /// <summary>
        /// 返回一个标志，指示指定的角色是否为给定用户的成员
        /// </summary>
        /// <param name="role">角色实体</param>
        /// <param name="userId">用户编号</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns>包含一个布尔值的<see cref="Task" />结果</returns>
        public virtual async Task<bool> IsInUserAsync(TRole role, string userId, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNullOrEmpty(userId, nameof(userId));

            TUserKey userKey = _userManager.Users.Where(m => m.Id.Equals(userId.CastTo<TUserKey>())).Select(m => m.Id).FirstOrDefault();
            if (Equals(userKey, default(TUserKey)))
            {
                throw new InvalidOperationException(I18N.T("用户 {0} 不存在", userId));
            }
            bool exist = _userRoleRepository.QueryAsNoTracking(m => m.UserId.Equals(userKey) && m.RoleId.Equals(role.Id)).Any();
            return await Task.FromResult(exist);
        }
        #endregion
        #region "返回作为用户成员的角色列表"
        /// <summary>
        /// 返回作为用户成员的角色列表
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns>包含角色集合的<see cref="Task" />结果</returns>
        public virtual async Task<IList<TRole>> GetRolesInUserAsync(string userId, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNullOrEmpty(userId, nameof(userId));

            TUserKey userKey = _userManager.Users.Where(m => m.Id.Equals(userId.CastTo<TUserKey>())).Select(m => m.Id).FirstOrDefault();
            if (Equals(userKey, default(TUserKey)))
            {
                throw new InvalidOperationException(I18N.T("用户 {0} 不存在", userId));
            }
            List<TRoleKey> roleIds = _userRoleRepository.QueryAsNoTracking(m => m.UserId.Equals(userKey)).Select(m => m.RoleId).ToList();
            IList<TRole> roles = _roleRepository.QueryAsNoTracking(m => roleIds.Contains(m.Id)).ToList();
            return await Task.FromResult(roles);
        }
        #endregion

        #endregion

        #region "方法 - Implementation of IRoleClaimStore<TRole>"
        #region "异步获取属于指定<paramref name="role"/>的<see cref="Claim"/>的列表"
        /// <summary>
        /// 异步获取属于指定<paramref name="role"/>的<see cref="Claim"/>的列表
        /// </summary>
        /// <param name="role">要检索的角色</param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns>
        /// 包含<see cref="IList{Claim}" />的<see cref="Task" />结果
        /// </returns>
        public virtual async Task<IList<Claim>> GetClaimsAsync(TRole role, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            IList<Claim> list = _roleClaimRepository.QueryAsNoTracking(m => m.RoleId.Equals(role.Id)).Select(n => new Claim(n.ClaimType, n.ClaimValue)).ToList();
            return await Task.FromResult(list);
        }
        #endregion
        #region "异步向角色添加新声明"
        /// <summary>
        /// 异步向角色添加新声明
        /// </summary>
        /// <param name="role">要向其添加声明的角色</param>
        /// <param name="claim">将要添加的<see cref="Claim" /></param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns>表示异步操作的任务对象</returns>
        public virtual async Task AddClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNull(claim, nameof(claim));

            TRoleClaim roleClaim = new TRoleClaim() { RoleId = role.Id, ClaimType = claim.Type, ClaimValue = claim.Value };
            await _roleClaimRepository.InsertAsync(roleClaim);
        }
        #endregion
        #region "异步从角色中移除声明"
        /// <summary>
        /// 异步从角色中移除声明
        /// </summary>
        /// <param name="role">从中移除声明的角色</param>
        /// <param name="claim">将要移除的<see cref="Claim" /></param>
        /// <param name="cancellationToken"><see cref="CancellationToken" />用于传播应取消操作的通知</param>
        /// <returns>表示异步操作的任务对象</returns>
        public virtual async Task RemoveClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNull(claim, nameof(claim));

            await _roleClaimRepository.DeleteBatchAsync(m => m.RoleId.Equals(role.Id) && m.ClaimValue == claim.Type && m.ClaimValue == claim.Value);
        }
        #endregion

        #endregion

        #region "方法 - Implementation of IRoleOrganizationStore<TRole>"
        #region "将指定的角色添加到组织机构"
        /// <summary>
        /// 将指定的角色添加到组织机构
        /// </summary>
        /// <param name="role">角色数据</param>
        /// <param name="organizationId">组织机构编号</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />结果</returns>
        public virtual async Task<OperationResult> AddToOrganizationAsync(TRole role, string organizationId, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNullOrEmpty(organizationId, nameof(organizationId));

            TOrganizationKey organizationKey = _organizationRepository.QueryAsNoTracking(m => m.Id.Equals(ConvertIdFromString(organizationId))).Select(m => m.Id).FirstOrDefault();
            if (Equals(organizationKey, default(TOrganizationKey)))
            {
                throw new InvalidOperationException(I18N.T("组织机构 {0} 不存在", organizationId));
            }
            TRoleOrganization roleOrganization = new() { OrganizationId = organizationKey, RoleId = role.Id };
            return await _roleOrganizationRepository.InsertAsync(roleOrganization);
        }
        #endregion
        #region "将指定的角色添加到组织机构集合"
        /// <summary>
        /// 将指定的角色添加到组织机构集合
        /// </summary>
        /// <param name="role">角色数据</param>
        /// <param name="organizationIds">组织机构编号集合</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="OperationResult" /></returns>
        public virtual async Task<OperationResult> AddToOrganizationsAsync(TRole role, string[] organizationIds, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNull(organizationIds, nameof(organizationIds));

            foreach (var organizationId in organizationIds)
            {
                var result = await AddToOrganizationAsync(role, organizationId, cancellationToken);
                if (!result.Succeeded)
                {
                    return result;
                }
            }
            return OperationResult.Success();
        }
        #endregion
        #region "从组织机构中删除指定的角色"
        /// <summary>
        /// 从组织机构中删除指定的角色
        /// </summary>
        /// <param name="role">角色数据</param>
        /// <param name="organizationId">组织机构编号</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />结果</returns>
        public virtual async Task<OperationResult> RemoveFromOrganizationAsync(TRole role, string organizationId, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNullOrEmpty(organizationId, nameof(organizationId));

            TOrganization organization = _organizationRepository.QueryAsNoTracking().FirstOrDefault(m => m.Id.Equals(ConvertIdFromString(organizationId))) ?? throw new InvalidOperationException(I18N.T("组织机构 {0} 不存在", organizationId));
            if (role.IsSystem && organization.IsSystem)
            {
                throw new InvalidOperationException(I18N.T("系统角色 {0} 的系统组织机构 {1} 不能移除", role.Name, organization.Name));
            }
            return await _roleOrganizationRepository.DeleteBatchAsync(m => m.RoleId.Equals(role.Id) && m.OrganizationId.Equals(organization.Id));
        }
        #endregion
        #region "从组织机构集合中删除指定的角色"
        /// <summary>
        /// 从组织机构集合中删除指定的角色
        /// </summary>
        /// <param name="role">角色数据</param>
        /// <param name="organizationIds">组织机构编号集合</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns><see cref="Task" />表示一个异步的<see cref="OperationResult" /></returns>
        public virtual async Task<OperationResult> RemoveFromOrganizationsAsync(TRole role, string[] organizationIds, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNull(organizationIds, nameof(organizationIds));

            foreach (var organizationId in organizationIds)
            {
                var result = await RemoveFromOrganizationAsync(role, organizationId, cancellationToken);
                if (!result.Succeeded)
                {
                    return result;
                }
            }
            return OperationResult.Success();
        }
        #endregion
        #region "获取指定角色所属的组织机构编号列表"
        /// <summary>
        /// 获取指定角色所属的组织机构编号列表
        /// </summary>
        /// <param name="role">角色数据</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns>包含组织机构编号集合的<see cref="Task" />结果</returns>
        public virtual async Task<IList<string>> GetOrganizationsAsync(TRole role, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));

            IList<string> list = _roleOrganizationRepository.QueryAsNoTracking(m => m.RoleId.Equals(role.Id)).Select(m => m.OrganizationId.ToString()).ToList();
            return await Task.FromResult(list);
        }
        #endregion
        #region "返回一个标志，指示指定的角色是否为给定组织机构的成员"
        /// <summary>
        /// 返回一个标志，指示指定的角色是否为给定组织机构的成员
        /// </summary>
        /// <param name="role">角色数据</param>
        /// <param name="organizationId">组织机构编号</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns>包含布尔值的<see cref="Task" />结果</returns>
        public virtual async Task<bool> IsInOrganizationAsync(TRole role, string organizationId, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNull(role, nameof(role));
            Check.NotNullOrEmpty(organizationId, nameof(organizationId));

            TOrganizationKey organizationKey = _organizationRepository.QueryAsNoTracking(m => m.Id.Equals(ConvertIdFromString(organizationId))).Select(m => m.Id).FirstOrDefault();
            if (Equals(organizationKey, default(TOrganizationKey)))
            {
                throw new InvalidOperationException(I18N.T("组织机构 {0} 不存在", organizationId));
            }
            bool exist = _roleOrganizationRepository.QueryAsNoTracking(m => m.RoleId.Equals(role.Id) && m.OrganizationId.Equals(organizationKey)).Any();
            return await Task.FromResult(exist);
        }
        #endregion
        #region "返回作为组织机构成员的角色列表"
        /// <summary>
        /// 返回作为组织机构成员的角色列表
        /// </summary>
        /// <param name="organizationId">组织机构编号</param>
        /// <param name="cancellationToken">用于传播应取消操作的通知</param>
        /// <returns>包含角色集合的<see cref="Task" />结果</returns>
        public virtual async Task<IList<TRole>> GetRolesInOrganizationAsync(string organizationId, CancellationToken cancellationToken = new CancellationToken())
        {
            cancellationToken.ThrowIfCancellationRequested();
            ThrowIfDisposed();
            Check.NotNullOrEmpty(organizationId, nameof(organizationId));

            TOrganizationKey organizationKey = _organizationRepository.QueryAsNoTracking(m => m.Id.Equals(ConvertIdFromString(organizationId))).Select(m => m.Id).FirstOrDefault();
            if (Equals(organizationKey, default(TOrganizationKey)))
            {
                throw new InvalidOperationException(I18N.T("组织机构 {0} 不存在", organizationId));
            }
            List<TRoleKey> roleIds = _roleOrganizationRepository.QueryAsNoTracking(m => m.OrganizationId.Equals(organizationKey)).Select(m => m.RoleId).ToList();
            IList<TRole> roles = _roleRepository.QueryAsNoTracking(m => roleIds.Contains(m.Id)).ToList();
            return await Task.FromResult(roles);
        }
        #endregion

        #endregion

    }
    #endregion

}
